package org.codehaus.activemq.ra;

import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;

public class CircularQueue
{
  private final int size;
  private final SynchronizedBoolean stopping;
  private final Object[] contents;
  private final Object mutex = new Object();

  private int start = 0;

  private int end = 0;

  public CircularQueue(int size, SynchronizedBoolean stopping) {
    this.size = size;
    this.contents = new Object[size];
    this.stopping = stopping;
  }

  public Object get() {
    synchronized (this.mutex)
    {
      Object ew = this.contents[this.start];
      if (ew != null) {
        this.start += 1;
        if (this.start == this.contents.length) {
          this.start = 0;
        }
        return ew;
      }
      try {
        this.mutex.wait();
        if (this.stopping.get())
          return null;
      }
      catch (Exception e) {
        return null;
      }
    }
	return null;
  }

  public void returnObject(Object worker)
  {
    synchronized (this.mutex) {
      this.contents[(this.end++)] = worker;
      if (this.end == this.contents.length) {
        this.end = 0;
      }
      this.mutex.notify();
    }
  }

  public int size() {
    return this.contents.length;
  }

  public void drain() {
    int i = 0;
    while (i < this.size)
      if (get() != null)
        i++;
  }

  public void notifyWaiting()
  {
    synchronized (this.mutex) {
      this.mutex.notifyAll();
    }
  }
}